﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace dbones.PlugIn.Test
{
    /// <summary>
    /// Summary description for UnitTest1
    /// </summary>
    [TestClass]
    public class PlugInUnitTest
    {
       

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        [TestMethod]
        public void AttachedSupportedInterface()
        {
            TinyPlug mgr = new TinyPlug();
            mgr.AddSupportedInterface<ITestLogger>();
            
            Assert.AreEqual(1, mgr.SupportedInterfaces().Count());
        }

        [TestMethod]
        public void CreateDefaultInstanceWhenThereIsOnlyOnePlugIn()
        {
            TinyPlug mgr = new TinyPlug();
            mgr.AddSupportedInterface<ITestLogger>();

            mgr.RegisterPlugIn<ITestLogger,TestLogger>();                
            ITestLogger logger = mgr.CreateInstance<ITestLogger>();

            Assert.AreEqual("name", ((IPlugInProvider)logger).Name);

        }

        [TestMethod]
        public void CreateDefaultInstanceWhenThereIsTwoPlugInsUsingDefault()
        {
            //Arrage
            TinyPlug mgr = new TinyPlug();
            mgr.AddSupportedInterface<ITestLogger>();

            mgr.RegisterPlugIn<ITestLogger, TestLogger>()
                .RegisterPlugIn<ITestLogger, TestLogger2>();

            mgr.PlugInsFor<ITestLogger>().ElementAt(1).IsDefault = true;
            
            //Action
            ITestLogger logger = mgr.CreateInstance<ITestLogger>();

            //Assert
            Assert.AreEqual(typeof(TestLogger2), logger.GetType());
        }

        [TestMethod]
        public void ChangingTheDefault()
        {
            //Arrage
            TinyPlug mgr = new TinyPlug();
            mgr.AddSupportedInterface<ITestLogger>();

            mgr.RegisterPlugIn<ITestLogger, TestLogger>()
                .RegisterPlugIn<ITestLogger, TestLogger2>()
                .RegisterPlugIn<ITestLogger, TestLogger3>();
            //Action
            mgr.PlugInsFor<ITestLogger>().ElementAt(1).IsDefault = true;
            mgr.PlugInsFor<ITestLogger>().ElementAt(0).IsDefault = true;
            ITestLogger logger = mgr.CreateInstance<ITestLogger>();

            //Assert
            Assert.AreEqual(typeof(TestLogger), logger.GetType());
            Assert.AreEqual(true, mgr.PlugInsFor<ITestLogger>().ElementAt(0).IsDefault);
            Assert.AreEqual(false, mgr.PlugInsFor<ITestLogger>().ElementAt(1).IsDefault);
            Assert.AreEqual(false, mgr.PlugInsFor<ITestLogger>().ElementAt(2).IsDefault);
        }

        [TestMethod]
        public void CreateSpecifiedInstance()
        {
            //Arrage
            TinyPlug mgr = new TinyPlug();
            mgr.AddSupportedInterface<ITestLogger>();

            mgr.RegisterPlugIn<ITestLogger, TestLogger>()
                .RegisterPlugIn<ITestLogger, TestLogger2>()
                .RegisterPlugIn<ITestLogger, TestLogger3>();

            mgr.PlugInsFor<ITestLogger>().ElementAt(1).IsDefault = true;
            ActualPlugIn actualPlugIn = mgr.PlugInsFor<ITestLogger>().ElementAt(0);

            //Action           
            ITestLogger logger = mgr.CreateInstance<ITestLogger>(actualPlugIn);

            //Assert
            Assert.AreEqual(typeof(TestLogger), logger.GetType());
        }

        [TestMethod]
        public void MoreThanOneSupportedInstance()
        {
            //Arrage
            TinyPlug mgr = new TinyPlug();
            mgr.AddSupportedInterface<ITestLogger>()
                .AddSupportedInterface<INotifier>();

            mgr.RegisterPlugIn<ITestLogger, TestLogger>()
                .RegisterPlugIn<ITestLogger, TestLogger2>()
                .RegisterPlugIn<ITestLogger, TestLogger3>()
                .RegisterPlugIn<INotifier, TestNotifier>();

            //Action           
            INotifier notifier = mgr.CreateInstance<INotifier>();

            //Assert
            Assert.AreEqual(typeof(TestNotifier), notifier.GetType());
        }

        [TestMethod]
        public void PlugInWhichSupportsMoreThanOneContract()
        {
            //Arrage
            TinyPlug mgr = new TinyPlug();
            mgr.AddSupportedInterface<ITestLogger>()
                .AddSupportedInterface<INotifier>();

            //Action           
            mgr.RegisterPlugInToAny(typeof(TestNotifyLogger));

            //Assert
            Assert.AreEqual(1, mgr.PlugInsFor(typeof(INotifier)).Count());
            Assert.AreEqual(1, mgr.PlugInsFor(typeof(ITestLogger)).Count());
        }

        [TestMethod]
        public void SearchAssemblyForSupportedPlugIns()
        {
            //Arrage
            TinyPlug mgr = new TinyPlug();
            mgr.AddSupportedInterface<INotifier>();

            //Action           
            mgr.RegisterPlugIn<INotifier>(typeof(INotifier).Assembly);

            //Assert
            Assert.AreEqual(2, mgr.PlugInsFor(typeof(INotifier)).Count());
            //Assert.AreEqual(1, mgr.PlugInsFor(typeof(ITestLogger)).Count());
        }

        [TestMethod]
        public void SearchAssemblyForAnySupportedPlugIns()
        {
            //Arrage
            TinyPlug mgr = new TinyPlug();
            mgr.AddSupportedInterface<INotifier>()
                .AddSupportedInterface<ITestLogger>();

            //Action           
            mgr.RegisterPlugInToAny(typeof(INotifier).Assembly);

            //Assert
            Assert.AreEqual(2, mgr.PlugInsFor(typeof(INotifier)).Count());
            Assert.AreEqual(2, mgr.PlugInsFor(typeof(ITestLogger)).Count());
        }
    }
}
